package main

import (
	"flag"
	"os"
	"time"

	"verifyCode/internal/conf"
	"verifyCode/pkg/kratoslog"

	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/config"
	"github.com/go-kratos/kratos/v2/config/file"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/transport/http"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"

	kratoszap "github.com/go-kratos/kratos/contrib/log/zap/v2"

	_ "go.uber.org/automaxprocs"
)

const TimeFormat = "2006-01-02 15:04:05.000"

// go build -ldflags "-X main.Version=x.y.z"
var (
	// Name is the name of the compiled software.
	Name string
	// Version is the version of the compiled software.
	Version string
	// flagconf is the config flag.
	flagconf string

	id, _ = os.Hostname()
)

func init() {
	flag.StringVar(&flagconf, "conf", "../../configs", "config path, eg: -conf config.yaml")
}

func newApp(logger log.Logger, hs *http.Server) *kratos.App {
	return kratos.New(
		kratos.ID(id),
		kratos.Name(Name),
		kratos.Version(Version),
		kratos.Metadata(map[string]string{}),
		kratos.Logger(logger),
		kratos.Server(
			// gs,
			hs,
		),
	)
}

func main() {
	flag.Parse()
	// logger := log.With(log.NewStdLogger(),
	// 	"ts", log.DefaultTimestamp,
	// 	"caller", log.DefaultCaller,
	// "service.id", id,
	// "service.name", Name,
	// "service.version", Version,
	// "trace.id", tracing.TraceID(),
	// "span.id", tracing.SpanID(),
	// )

	c := config.New(
		config.WithSource(
			file.NewSource(flagconf),
		),
	)
	defer c.Close()

	if err := c.Load(); err != nil {
		panic(err)
	}

	var bc conf.Bootstrap
	if err := c.Scan(&bc); err != nil {
		panic(err)
	}

	kLog := &kratoslog.Log{
		Console:    bc.Log.Console,
		Compress:   bc.Log.Compress,
		RunMode:    "kratos",
		Level:      bc.Log.Level,
		Dir:        bc.Log.Dir,
		Encoding:   bc.Log.Encoding,
		FileName:   bc.Log.FileName,
		MaxAge:     int(bc.Log.MaxAge),
		MaxSize:    int(bc.Log.MaxSize),
		MaxBackups: int(bc.Log.MaxBackups),
	}
	logger := log.With(kratoszap.NewLogger(kratoslog.NewZapLogger(kLog)), "caller", log.DefaultCaller)
	tlog := log.NewHelper(log.NewFilter(logger, log.FilterLevel(log.ParseLevel(kLog.Level))))
	tlog.Debugw("msg", "kratos log test", "test", "debug")
	tlog.Infow("msg", "kratos log test", "test", "info")
	tlog.Errorw("msg", "kratos log test", "test", "err")
	tlog.Warnw("msg", "kratos log test", "test", "warn")

	app, cleanup, err := wireApp(bc.Server, bc.Data, logger)
	if err != nil {
		panic(err)
	}
	defer cleanup()

	// start and wait for stop signal
	if err := app.Run(); err != nil {
		panic(err)
	}
}

func zLog() *kratoszap.Logger {
	f, err := os.OpenFile("test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return nil
	}
	writeSyncer := zapcore.AddSync(f)

	encoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
		TimeKey:        "ts",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalColorLevelEncoder,
		EncodeTime:     timeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   callerEncoder,
	})
	core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
	z := zap.New(core, zap.AddCallerSkip(2))

	logger := kratoszap.NewLogger(z)
	return logger
}

func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString("[" + t.Format(TimeFormat) + "]")
}

// func levelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
// 	s, ok := _levelToCapitalColorString[level]
// 	if !ok {
// 		s = _unknownLevelColor.Add(level.CapitalString())
// 	}
// 	enc.AppendString("[" + s + "]")
// }

func callerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString("[" + caller.TrimmedPath() + "]")
}
